#include "UdpClient.hpp"
#include "Comm.hpp"
#include "Log.hpp"
#include <iostream>
#include <string>
#include <cstring>
// #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace LogModule;
// ./client_udp serverip serverport
int main(int argc, char *argv[])
{
	if (argc != 3)
	{
		std::cerr << "Usage: " << argv[0] << " serverip serverport" << std::endl;
		Die(1);
	}

	std::string serverip = argv[1];
	uint16_t serverport = std::stoi(argv[2]);

	// 创建socket
	int sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0)
	{
		std::cerr << "socket error" << std::endl;
		Die(2);
	}
	// 填充server信息
	struct sockaddr_in server;
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = ::htons(serverport);
	server.sin_addr.s_addr = ::inet_addr(serverip.c_str());

	while (true)
	{
		std::cout << "Please Enter# ";
		std::string message;
		std::getline(std::cin, message);
		// client 不需要bind吗？socket <-> socket
		// client必须也要有自己的ip和端口！但是客户端，不需要自己显示的调用bind！！
		// 而是，客户端首次sendto消息的时候，由OS自动进行bind
		// 1. 如何理解client自动随机bind端口号？ 一个端口号，只能被一个进程bind
		// 2. 如何理解server要显示的bind？服务器的端口号，必须稳定！！必须是众所周知且不能改变轻易改变的!
		int n = ::sendto(sockfd, message.c_str(), message.size(), 0, CONV(&server), sizeof(server));
		if(n < 0)
		{
			std::cerr << "sendto error" << std::endl;
			Die(3);
		}
		
		struct sockaddr_in tmp;
		socklen_t len = sizeof(tmp);
		char unbuffer[1024];
		n = ::recvfrom(sockfd,unbuffer,sizeof(unbuffer)-1,0,CONV(&tmp),&len);
		if(n > 0)
		{
			unbuffer[n] = 0;
			LOG(LogLevel::DEBUG) << "server say@: " << unbuffer;
		}
	}
	return 0;
}